#ifndef GAME_WORLD_H
#define GAME_WORLD_H

#include "ClippingPlane.h"
#include "GroupManager.h"
#include "OverlayMenu.h"
#include "GUISound.h"
#include "Chatbox.hpp"
#include "Camera.hpp"
#include "General Structures.hpp"
#include "utils.h"
#include "GameBoard.h"
#include "PathManager.h"
#include "PathPlanner.h"
#include "PoolManager.h"

#define World GameWorld::Instance()
#define ClipPlane World->GetClipPlane()
#define WorldMap World->GetMap()
#define ScreenMouse World->ScreenMousePos()
#define GameMouse World->GameMousePos()

class BaseGameEnity;
class GameBoard;
class Character;

typedef SparseGraph<NavGraphNode<void*>, GraphEdge> NavGraph;
typedef list<BaseGameEntity*> EntityList;
typedef list<Character*> CharacterList;

class GameWorld
{
// The friend class responsible for handling incoming events during the game
friend class EventHandler;
public:
	typedef SparseGraph<NavGraphNode<void*>, GraphEdge> NavGraph;

private:
	// Game World is a singleton
	GameWorld();
	GameWorld(const GameWorld& world) {};
	
	ClippingPlane	m_ClipPlane;
	Camera			m_Camera;
	GameBoard*		m_pGameMap;



	// Graphical User Interfaces
	OverlayMenu		m_OverlayMenu;
	GUISound		m_SoundGUI;

	// All the entities in the alive in the game world
	EntityList		m_Entities;

	// A subset of the EntityList, containing all entities that are characters
	CharacterList	m_Characters;

	// Contains all characters that are currently selected
	CharacterList	m_SelectedCharacters;

	Chatbox			m_Chatbox;

	Vector2D		m_ScreenMousePos;
	Vector2D		m_GameMousePos;

	GameRectangle	m_SelectionBox;

	Uint8*			m_Keystates;
	
	PathManager<PathPlanner>* m_pPathManager;

	PoolManager m_PoolManager;

	// Update Functions
	void UpdateEntityPanel();
	void UpdateGameEntities(double time_elapsed);
	void UpdateSelectionBox();
	void UpdateGameMousePosition();

	// These updates are called in EventHandler
	void UpdateMousePosition(SDL_Event& event); // Takes a MOUSEMOTION event

	// Render Functions
	void RenderGameEntities();
	void RenderSelectionBox();

public:
	
	BaseGameEntity* m_pSctEnt;

	static GameWorld* Instance() {static GameWorld instance; return &instance;}
	void Initialize();

	// Render functions
	void Render();


	// Update functions
	void Update(double time_elapsed);
	void UpdateMinimapEntity(int ID, const Vector2D& position);
	

	void LoadMap(string filename);

	void FreeMemory();

	void AddEntity(BaseGameEntity* aCharacter);

	void ToggleSoundGUI();

	bool m_bRenderCells;


	// General Utils. 
	void EnforceNonPenetration(BaseGameEntity* anEntity );
	double CalculateRate(int PlayerID);
	bool IsPathObstructed(Vector2D Start, Vector2D end, double BoundRadius);

	// Some (actually several) Useful Gets
	ClippingPlane*	GetClipPlane();
	GameBoard*		GetMap();
	NavGraph*		GetNavGraph();

	Point			ScreenMousePos();
	Point			GameMousePos();
	Uint8*		GetKeystates();

	EntityList		Entities();
	GameRectangle	SelectionBox();
	PoolManager&	GetPoolManager();
	PathManager<PathPlanner>* const GetPathManager() {return m_pPathManager;}

	
};

#endif